package com.youxin.busfoundation.common.es;

import java.util.ArrayList;

import java.util.List;
import java.util.Map;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;

import com.youxin.busfoundation.bean.ent.RequestEntInfo;
import com.youxin.busfoundation.common.GlobalConfig;
import com.youxin.busfoundation.common.es.bean.CompanyInfoBean;
import com.youxin.busfoundation.common.es.bean.RequestQueryLeadsBean;
import com.youxin.busfoundation.config.EsConfig;
import com.youxin.busfoundation.enums.EnterpriseEstablishTimeType;
import com.youxin.busfoundation.enums.EnterpriseRegisteredCapitalType;
import com.youxin.busfoundation.enums.EnterpriseScaleType;
import com.youxin.busfoundation.utils.es.EsBasePage;
import com.youxin.foundation.interfaces.Convert;
import com.youxin.foundation.lang.BaseException;
import com.youxin.foundation.utils.ArrayUtils;
import com.youxin.foundation.utils.DateUtil;
import com.youxin.foundation.utils.JsonUtils;
import com.youxin.foundation.utils.StringUtils;

/**
 * 搜索公司
 * 
 * @author yingde.cao
 *
 */
public class SearchComapny<T> extends BaseSearch<T> {

	private static String[] COMPANY_DEFAULT_SEARCH_FIELDS = new String[] { "uid", "full_name", "short_name",
			"legal_person_name", "reg_capital", "scale", "industry", "industry_small", "approved_time", "area",
			"from_time", "reg_time", "reg_unit" };// , "introduction"

	public SearchComapny(Convert<T> convert) {
		super(convert);
	}

	public SearchComapny() {
		super();
	}

	/**
	 * 搜索公司信息
	 * 
	 * @param bean
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public EsBasePage<Object> queryList(RequestQueryLeadsBean bean, Class<T> cls) throws Exception {

		try {
			String keywords = org.apache.commons.lang3.StringUtils.trim(bean.getKeywords());

			BoolQueryBuilder queryBuilder = null;
			if (!StringUtils.isNullOrEmpty(keywords)) {
				if (queryBuilder == null) {
					queryBuilder = new BoolQueryBuilder();
				}
				queryBuilder.must(QueryBuilders.multiMatchQuery(keywords, "full_name", "short_name"));// ,
																										// "introduction"
			}
			/**
			 * 分类查询
			 */
			BoolQueryBuilder classifyQueryBuilder = addClassify(bean);
			if (classifyQueryBuilder != null) {
				if (queryBuilder == null) {
					queryBuilder = new BoolQueryBuilder();
				}
				queryBuilder.must(classifyQueryBuilder);
			}
			/**
			 * 企业规模
			 */
			if (!ArrayUtils.isEmpty(bean.getScale())) {
				BoolQueryBuilder tempQueryBuilder = null;
				for (Integer item : bean.getScale()) {
					if (item.intValue() == EnterpriseScaleType.All.getValue()) {
						continue;
					}
					if (tempQueryBuilder == null) {
						tempQueryBuilder = new BoolQueryBuilder();
					}
					tempQueryBuilder.should(QueryBuilders.termQuery("scale", item.intValue()));
				}
				if (tempQueryBuilder != null) {
					if (queryBuilder == null) {
						queryBuilder = new BoolQueryBuilder();
					}
					queryBuilder.must(tempQueryBuilder);
				}
			}

			/**
			 * 成立时间
			 */
			if (!ArrayUtils.isEmpty(bean.getEstablishTime())) {
				BoolQueryBuilder tempQueryBuilder = null;
				for (Integer item : bean.getEstablishTime()) {
					if (item.intValue() == EnterpriseEstablishTimeType.All.getValue()) {
						continue;
					}
					EnterpriseEstablishTimeType type = EnterpriseEstablishTimeType.valueOf(item);
					if (type == null) {
						continue;
					}
					if (tempQueryBuilder == null) {
						tempQueryBuilder = new BoolQueryBuilder();
					}

					String startTime = DateUtil.dateToString(type.startDate());
					String endTime = DateUtil.dateToString(type.endDate());
					tempQueryBuilder.should(QueryBuilders.rangeQuery("reg_time").gte(startTime).lt(endTime));
				}
				if (tempQueryBuilder != null) {
					if (queryBuilder == null) {
						queryBuilder = new BoolQueryBuilder();
					}
					queryBuilder.must(tempQueryBuilder);
				}
			}

			/**
			 * 注册资本
			 */
			if (!ArrayUtils.isEmpty(bean.getRegisteredCapital())) {
				BoolQueryBuilder tempQueryBuilder = null;
				for (Integer item : bean.getRegisteredCapital()) {
					if (item.intValue() == EnterpriseRegisteredCapitalType.All.getValue()) {
						continue;
					}

					if (tempQueryBuilder == null) {
						tempQueryBuilder = new BoolQueryBuilder();
					}
					EnterpriseRegisteredCapitalType type = EnterpriseRegisteredCapitalType.valueOf(item);
					if (type == null) {
						continue;
					}
					int min = type.getMin();
					int max = type.getMax();
					tempQueryBuilder.should(QueryBuilders.rangeQuery("reg_capital").gte(min).lt(max));
				}

				if (tempQueryBuilder != null) {
					if (queryBuilder == null) {
						queryBuilder = new BoolQueryBuilder();
					}
					queryBuilder.must(tempQueryBuilder);
				}
			}

			BoolQueryBuilder tempQueryBuilder = null;
			/**
			 * 查询城市
			 */
			if (!StringUtils.isNullOrEmpty(bean.getCity())) {
				if (tempQueryBuilder == null) {
					tempQueryBuilder = new BoolQueryBuilder();
				}
				tempQueryBuilder.should(QueryBuilders.termQuery("area", bean.getCity()));
			} else {
				/**
				 * 查询省份
				 */
				if (!StringUtils.isNullOrEmpty(bean.getProvince())) {
					if (tempQueryBuilder == null) {
						tempQueryBuilder = new BoolQueryBuilder();
					}
					tempQueryBuilder.should(QueryBuilders.termQuery("area", bean.getProvince()));
				}
			}
			if (tempQueryBuilder != null) {
				if (queryBuilder == null) {
					queryBuilder = new BoolQueryBuilder();
				}
				queryBuilder.must(tempQueryBuilder);
			}

			if (!ArrayUtils.isEmpty(bean.getFilterUids())) {
				if (queryBuilder == null) {
					queryBuilder = new BoolQueryBuilder();
				}
				queryBuilder.mustNot(QueryBuilders.termsQuery("_id", bean.getFilterUids()));
			}
			// srb.setQuery(queryBuilder);
			// srb.setFetchSource(includes, excludes)

			return queryList(bean, cls, queryBuilder, (srb) -> {
				if (!StringUtils.isNullOrEmpty(bean.getBy())) {
					srb.addSort(bean.getBy(), bean.getOrderBy() == 1 ? SortOrder.DESC : SortOrder.ASC);
				}
				if (!StringUtils.isNullOrEmpty(bean.getPreTags()) && !StringUtils.isNullOrEmpty(bean.getPostTags())) {
					HighlightBuilder hb = new HighlightBuilder();
					hb.preTags(bean.getPreTags());
					hb.postTags(bean.getPostTags());
					// hb.field("*").requireFieldMatch(false);
					hb.field("full_name").field("short_name");
					// .field("introduction");
					// hb.field("full_name").field("short_name").field("introduction").preTags(bean.getPreTags()).postTags(bean.getPostTags());
					srb.highlighter(hb);
				}
				// String[] fields = new String[] { "uid", "full_name",
				// "short_name", "introduction", "legal_person_name",
				// "reg_capital", "scale", "industry", "industry_small",
				// "approved_time", "area", "from_time",
				// "estiblish_time","reg_unit" };
				srb.setFetchSource(COMPANY_DEFAULT_SEARCH_FIELDS, null);
			}, new String[] { EsConfig.getConfig().getCompanyname() }, null);

		} catch (Exception e) {
			throw e;
		} finally {

		}
	}

	/**
	 * 企业画像查询 CompanyInfoBean
	 * 
	 * @param requestBean
	 *            公司uid信息 RequestEntInfo
	 * @return CompanyInfoBean
	 * @throws Exception
	 */
	public CompanyInfoBean queryCompanyInfo(RequestEntInfo requestBean) throws Exception {
		Client client = EsClient.instance().getClient();
		try {
			SearchRequestBuilder srb = client.prepareSearch(EsConfig.getConfig().getCompanyname());
			srb.setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setExplain(true);
			srb.setQuery(QueryBuilders.termQuery("uid", requestBean.getUid()));
			SearchResponse response = srb.execute().actionGet(GlobalConfig.ES_SEARCH_TIMEOUT);
			SearchHits hits = response.getHits();
			if (hits.getTotalHits() > 0) {
				SearchHit searchHit = hits.getAt(0);
				Map<String, Object> sourceMaps = searchHit.getSource();
				String sourceString = JsonUtils.objectToFasterxmlJsonString(sourceMaps);
				CompanyInfoBean bean = JsonUtils.stringToFasterxmlObject(sourceString, CompanyInfoBean.class);
				// String sourceString = hits.getAt(0).getSourceAsString();
				// CompanyInfoBean bean =
				// JsonUtils.stringToFasterxmlObject(sourceString,
				// CompanyInfoBean.class);
				if (bean == null) {
					// logger.error("uid:"+String.valueOf(requestBean.getUid())+",sourceString:"+sourceString);
					throw new BaseException(
							"数据转换错误:" + String.valueOf(requestBean.getUid()) + ":" + String.valueOf(sourceString));
				}
				return bean;
			}
			throw new BaseException("企业标识没有匹配到数据!uid:" + String.valueOf(requestBean.getUid()));
		} catch (Exception e) {
			throw e;
		} finally {
		}
	}

	/**
	 * 公司uid搜索公司信息一次查询
	 * 
	 * @description
	 * @param uids
	 * @return
	 * @throws Exception
	 */
	public List<CompanyInfoBean> queryCompanyInfos(List<String> uids) throws Exception {
		Client client = EsClient.instance().getClient();
		try {
			SearchRequestBuilder srb = client.prepareSearch(EsConfig.getConfig().getCompanyname());
			srb.setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setFrom(0).setSize(1000).setExplain(true);
			String[] terms = uids.toArray(new String[] {});
			srb.setQuery(QueryBuilders.termsQuery("uid", terms));
			SearchResponse response = srb.execute().actionGet(GlobalConfig.ES_SEARCH_TIMEOUT);
			SearchHits hits = response.getHits();
			List<CompanyInfoBean> list = new ArrayList<>(20);
			for (SearchHit item : hits) {
				Map<String, Object> sourceMaps = item.getSource();
				String sourceString = JsonUtils.objectToFasterxmlJsonString(sourceMaps);
				CompanyInfoBean bean = JsonUtils.stringToFasterxmlObject(sourceString, CompanyInfoBean.class);

				// String sourceString = item.getSourceAsString();
				// CompanyInfoBean bean =
				// JsonUtils.stringToFasterxmlObject(sourceString,
				// CompanyInfoBean.class);
				if (bean == null) {
					// logger.error("sourceString:"+sourceString);
					throw new BaseException("数据转换错误:" + sourceString);
				}
				list.add(bean);
			}
			return list;
		} catch (Exception e) {
			throw e;
		} finally {
		}
	}

	/**
	 * 公司uid搜索公司信息一次查询
	 * 
	 * @description
	 * @param uids
	 * @return
	 * @throws Exception
	 */
	public List<T> queryCompanyInfosByUids(List<String> uids, Class<T> modelCls) throws Exception {
		Client client = EsClient.instance().getClient();
		try {
			SearchRequestBuilder srb = client.prepareSearch(EsConfig.getConfig().getCompanyname());
			srb.setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setFrom(0).setSize(uids.size()).setExplain(true);
			String[] terms = uids.toArray(new String[] {});

			srb.setFetchSource(COMPANY_DEFAULT_SEARCH_FIELDS, null);
			srb.setQuery(QueryBuilders.termsQuery("uid", terms));
			SearchResponse response = srb.execute().actionGet(GlobalConfig.ES_SEARCH_TIMEOUT);
			SearchHits hits = response.getHits();
			List<T> list = new ArrayList<>(20);
			for (SearchHit item : hits) {
				Map<String, Object> sourceMaps = item.getSource();
				String sourceString = JsonUtils.objectToFasterxmlJsonString(sourceMaps);
				T bean = JsonUtils.stringToFasterxmlObject(sourceString, modelCls);

				// String sourceString = item.getSourceAsString();
				// CompanyInfoBean bean =
				// JsonUtils.stringToFasterxmlObject(sourceString,
				// CompanyInfoBean.class);
				if (bean == null) {
					logger.error("sourceString:" + sourceString);
					throw new BaseException("数据转换错误:" + sourceString);
				} else {
					if (convert != null) {
						convert.apply(bean);
					}
					list.add(bean);
				}
			}
			return list;
		} catch (Exception e) {
			throw e;
		} finally {
		}
	}

	public List<CompanyInfoBean> queryCompanyInfosContact(List<String> uids) throws Exception {
		Client client = EsClient.instance().getClient();
		try {
			SearchRequestBuilder srb = client.prepareSearch(EsConfig.getConfig().getCompanyname());
			srb.setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setFrom(0).setSize(1000).setExplain(true);
			String[] terms = uids.toArray(new String[] {});
			srb.setQuery(QueryBuilders.termsQuery("uid", terms));

			String[] fields = new String[] { "uid", "full_name", "short_name", "legal_person_name", "reg_capital",
					"scale", "industry", "industry_small", "approved_time", "area", "from_time", "estiblish_time",
					"reg_unit" };
			srb.setFetchSource(fields, null);

			SearchResponse response = srb.execute().actionGet(GlobalConfig.ES_SEARCH_TIMEOUT);
			SearchHits hits = response.getHits();
			List<CompanyInfoBean> list = new ArrayList<>(20);
			for (SearchHit item : hits) {
				Map<String, Object> sourceMaps = item.getSource();
				String sourceString = JsonUtils.objectToFasterxmlJsonString(sourceMaps);
				CompanyInfoBean bean = JsonUtils.stringToFasterxmlObject(sourceString, CompanyInfoBean.class);

				// String sourceString = item.getSourceAsString();
				// CompanyInfoBean bean =
				// JsonUtils.stringToFasterxmlObject(sourceString,
				// CompanyInfoBean.class);
				if (bean == null) {
					logger.error("queryCompanyInfosByUids:" + String.valueOf(sourceString));
					throw new BaseException("queryCompanyInfosContact数据转换错误:" + String.valueOf(sourceString));
				} else {

				}
				list.add(bean);
			}
			return list;
		} catch (Exception e) {
			throw e;
		} finally {
		}
	}

}
